﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Reflection;
using System.Data.SqlClient;
using CH.Easy.Utility;
using CH.TestData.Common;
using CH.TestData.Generate;
using CH.TestData.Provider;
using System.Threading;
using System.Xml.Linq;
using System.IO;

namespace CH.TestData
{
    public partial class FrmMain : Form
    {



        #region 初始化
        public FrmMain()
        {

            InitializeComponent();
            Init();
        }
        /// <summary>
        /// 初始化
        /// </summary>
        private void Init()
        {
            cbOutType.DataSource = new List<KeyValuePair<string, string>> 
            {
                new KeyValuePair<string,string>(Enum.GetName(typeof(OutType),OutType.MsSqlText), "MsSql2005脚本")
                //new KeyValuePair<string,string>(Enum.GetName(typeof(OutType),OutType.MsSqlDb), "MsSql2005数据库")
            };
            cbOutType.DisplayMember = "Value";
            cbOutType.ValueMember = "Key";
        }
        #endregion
        #region 生成数据
        /// <summary>
        /// 复制内容到剪贴板
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void txtResult_MouseClick(object sender, MouseEventArgs e)
        {
            if (!string.IsNullOrEmpty(txtResult.Text))
            {
                //txtResult.SelectAll();
                Clipboard.SetText(txtResult.Text);
                tslblMsg.Text = "已复制到剪贴板";
                tspbGenerate.Value = 0;
            }
        }
        /// <summary>
        /// 设置焦点 用于避免表选择时的滚动事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void plColumns_MouseEnter(object sender, EventArgs e)
        {
            plColumns.Focus();

        }
        /// <summary>
        /// 设置焦点 用于避免表选择时的滚动事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void gbColumns_MouseHover(object sender, EventArgs e)
        {
            plColumns.Focus();
        }
        /// <summary>
        /// 开始生成
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnCreate_Click(object sender, EventArgs e)
        {

            txtResult.Text = "";
            tspbGenerate.Value = 0;
            tslblMsg.Text = "准备就绪";




            List<IDataProvider> providers = new List<IDataProvider>();
            List<string> columns = new List<string>();
            Control[] cs = plColumns.Controls.Find("flpItem", false);
            if (cs == null || cs.Count() == 0)
            {
                MessageBox.Show("没有选择生成任何列!");
                return;
            }

            foreach (FlowLayoutPanel flp in cs)
            {
                TextBox txtColumnName = flp.Controls.Find("txtColumnName", false).First() as TextBox;
                columns.Add(txtColumnName.Text);


                ComboBox cbDataType = flp.Controls.Find("cbDataType", false).First() as ComboBox;
                IDataProvider idp = (IDataProvider)Assembly.GetExecutingAssembly().CreateInstance(cbDataType.SelectedValue.ToString());
                idp.SetDataSource(flp);
                providers.Add(idp);



            }

            int count = 0;
            if (!int.TryParse(txtCount.Text, out count))
            {
                count = 100;
                txtCount.Text = "100";
            }

            AbstractGenerate ag = (AbstractGenerate)Assembly.GetExecutingAssembly().CreateInstance("CH.TestData.Generate." + cbOutType.SelectedValue + "Generate");
            ag.GenerateCompleteEvent += new GenerateComplete(ag_GenerateCompleteEvent);
            ag.GenerateUpdateEvent += new GenerateUpdate(ag_GenerateUpdateEvent);
            tspbGenerate.Maximum = count;
            txtCount.Enabled = false;
            btnCreate.Enabled = false;
            string tableName = cbTableName.SelectedItem.ToString();

            new Thread(new ThreadStart(delegate
            {
                ag.Start(count, tableName, columns, providers);

            })).Start();



        }
        /// <summary>
        /// 更新生成进度
        /// </summary>
        /// <param name="result"></param>
        private void ag_GenerateUpdateEvent(string result)
        {
            Invoke(new MethodInvoker(delegate
            {
                tspbGenerate.Value++;
            }));
        }
        /// <summary>
        /// 生成完成
        /// </summary>
        /// <param name="result"></param>
        private void ag_GenerateCompleteEvent(string result)
        {
            Invoke(new MethodInvoker(delegate
            {
                txtCount.Enabled = true;
                btnCreate.Enabled = true;
                tabNav.SelectTab(1);
                txtResult.Text = result;
            }));
        }
        /// <summary>
        /// 设置生成数据类型
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cbDataType_SelectedIndexChanged(object sender, EventArgs e)
        {

            ComboBox cbDataType = (ComboBox)sender;
            FlowLayoutPanel flp = cbDataType.Parent.Controls.Find("flpCustom", false).First() as FlowLayoutPanel;
            flp.Controls.Clear();
            IDataProvider idp = (IDataProvider)Assembly.GetExecutingAssembly().CreateInstance(cbDataType.SelectedValue.ToString());
            idp.CreateOption(flp);
        }
        /// <summary>
        /// 删除列
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_Click(object sender, EventArgs e)
        {
            Control c = (Control)sender;
            plColumns.Controls.Remove(c.Parent);
        }
        /// <summary>
        /// 清空
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnClearColumn_Click(object sender, EventArgs e)
        {
            plColumns.Controls.Clear();
            btnCreate.Enabled = true;
        }
        /// <summary>
        /// 测试数据库连接
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnTest_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(txtConnectionString.Text))
            {
                MessageBox.Show("请填写数据库连接地址!");
                return;
            }

            DataTable dtTableName = DbSqlHelper.GetSchema(txtConnectionString.Text, "Tables", null);
            if (dtTableName.Rows.Count > 0)
            {

                cbTableName.Items.Clear();
                foreach (DataRow row in dtTableName.Rows)
                {
                    cbTableName.Items.Add(row["TABLE_NAME"]);
                }
                cbTableName.SelectedIndex = 0;
            }





        }
        /// <summary>
        /// 添加列
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnAddColumn_Click(object sender, EventArgs e)
        {
            AddColumn("");
        }
        /// <summary>
        /// 添加列
        /// </summary>
        /// <param name="columnName"></param>
        private void AddColumn(string columnName)
        {
            FlowLayoutPanel flp = new FlowLayoutPanel();
            flp.Name = "flpItem";
            flp.FlowDirection = FlowDirection.LeftToRight;
            flp.Dock = DockStyle.Top;
            flp.Height = 30;

            Button btn = new Button();
            btn.Width = 20;
            btn.Text = "-";
            btn.Click += new EventHandler(btn_Click);
            flp.Controls.Add(btn);



            TextBox txtColumnName = new TextBox();
            txtColumnName.Name = "txtColumnName";
            txtColumnName.Text = columnName;
            flp.Controls.Add(txtColumnName);

            ComboBox cbDataType = new ComboBox();
            cbDataType.DataSource = GetDataTypeList();
            cbDataType.Name = "cbDataType";
            cbDataType.DisplayMember = "Value";
            cbDataType.ValueMember = "Key";
            cbDataType.DropDownStyle = ComboBoxStyle.DropDownList;
            cbDataType.SelectedIndexChanged += new EventHandler(cbDataType_SelectedIndexChanged);
            flp.Controls.Add(cbDataType);

            FlowLayoutPanel flpCustom = new FlowLayoutPanel();
            flpCustom.FlowDirection = FlowDirection.LeftToRight;
            flpCustom.Name = "flpCustom";
            flpCustom.Width = plColumns.Width - 260;
            flpCustom.Margin = new Padding(0);
            flp.Controls.Add(flpCustom);





            plColumns.Controls.Add(flp);

        }
        /// <summary>
        /// 初始化 测试数据列
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cbTableName_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(txtConnectionString.Text))
            {
                MessageBox.Show("请填写数据库连接地址!");
                return;
            }


            ComboBox cb = (ComboBox)sender;
            string[] res = new string[4];
            res[2] = cb.SelectedItem.ToString();
            DataTable dtColumnsName = DbSqlHelper.GetSchema(txtConnectionString.Text, "Columns", res);
            if (dtColumnsName != null && dtColumnsName.Rows.Count > 0)
            {
                plColumns.Controls.Clear();
                foreach (DataRow row in dtColumnsName.Rows)
                {
                    AddColumn(row["COLUMN_NAME"].ToString());
                }
            }
        }
        /// <summary>
        /// 数据类型
        /// </summary>
        /// <returns></returns>
        private List<KeyValuePair<string, string>> GetDataTypeList()
        {
            List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>();
            Type[] ts = Assembly.GetExecutingAssembly().GetTypes();
            foreach (Type t in ts)
            {
                Type provider = t.GetInterface("IDataProvider", true);
                if (provider != null)
                {
                    object[] attrs = t.GetCustomAttributes(typeof(DataTypeNameAttribute), true);
                    if (attrs != null && attrs.Count() > 0)
                    {
                        DataTypeNameAttribute attr = (DataTypeNameAttribute)attrs.First();
                        list.Add(new KeyValuePair<string, string>(t.FullName, attr.Name));
                    }

                }
            }
            return list;

        }
        #endregion


        #region 生成字典
        XDocument xdoc = null;
        private void btnExcuteSqlString_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(txtConnectionString.Text))
            {
                MessageBox.Show("请输入数据库连接地址");
                return;
            }
            if (string.IsNullOrEmpty(txtSqlString.Text))
            {
                MessageBox.Show("请输入Sql查询语句");
                return;
            }
            DataTable dt = DbSqlHelper.ExecuteDataTable(txtConnectionString.Text, CommandType.Text, txtSqlString.Text);
            xdoc = new XDocument(new XDeclaration("1.0", "utf-8", "yes"), new XElement("Root"));
            xdoc.Root.Add(new XElement("Type", "Normal"));
            xdoc.Root.Add(new XElement("List"));
            foreach (DataRow row in dt.Rows)
            {
                if (cbUseCDATA.Checked)
                {
                    xdoc.Root.Element("List").Add(new XElement("Item", new XCData(row[0].ToString())));
                }
                else
                {
                    xdoc.Root.Element("List").Add(new XElement("Item", row[0].ToString()));
                }
            }

            txtPreview.Text = xdoc.ToString();

        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            if (xdoc == null)
            {
                return;
            }

            if (string.IsNullOrEmpty(txtFileName.Text))
            {
                MessageBox.Show("请输入文件名");
                return;
            }

            string path = AppDomain.CurrentDomain.BaseDirectory + @"Data\";
            if (!Directory.Exists(path))
            {
                Directory.Delete(path);
            }
            string fileName = path + txtFileName.Text + ".xml";
            xdoc.Save(fileName);
            MessageBox.Show("保存成功!(" + fileName + ")");

        }
        #endregion



















    }
}
